﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;


namespace ProjectNocturnalFool
{
    public enum ControlDepth
    {
        Background,
        GameBoard,
        NonDrag,
        Label,
        Drag,
        Modar,
    }

    public enum HorizontalAnchor
    {
        Left,
        Middle,
        Right,
        None
    }

    public enum VerticleAnchor
    {
        Top,
        Middle,
        Bottom,
        None
    }


    /// <summary>
    /// User Controls are used for displaying visual and UI elements on screen.
    /// </summary>
    class UserControl
    {
        #region Fields
                
        /// <summary>
        /// Background texture for the control
        /// </summary>
        protected Texture2D _bgTexture;

        /// <summary>
        /// Current Control state, used 
        /// </summary>
        public List<Tuple<string, int, int>> updateStatus = new List<Tuple<string, int, int>>();

        /// <summary>
        /// Anchors for resizing
        /// </summary>
        public HorizontalAnchor xAnchor = HorizontalAnchor.None;
        public VerticleAnchor yAnchor = VerticleAnchor.None;

        public bool expandWidth = false;

        /// <summary>
        /// If there should only be one object created and never removed (text messenger, tooltip, etc)
        /// </summary>
        public bool singleton { get; set; }

        /// <summary>
        /// If the control is hidden and inaccessable
        /// </summary>
        public bool hidden { get; set; }

        /// <summary>
        /// Sets if the window is modar (only selectable object)
        /// </summary>
        public bool modar { get; set; }

        /// <summary>
        /// Is the control dragable by holding
        /// </summary>
        private bool IsDraggable = false;
        public bool isDraggable
        {
            get { return IsDraggable; }
            set
            {
                IsDraggable = value;
                depth = IsDraggable == true ? ControlDepth.Drag : ControlDepth.NonDrag;
            }
        }

        /// <summary>
        /// Last position, used for drags
        /// </summary>
        private int lastX, lastY = 0;

        /// <summary>
        /// If the control is being hovered over by the mouse
        /// </summary>
        public bool Hover = false;

        /// <summary>
        /// Of the mouse is held down over this control
        /// </summary>
        public bool Held = false;

        /// <summary>
        /// If the control has focus (i.e been clicked on, activated, etc)
        /// </summary>
        public bool Selected = false;

        /// <summary>
        /// Get if the control has been clicked
        /// </summary>
        public bool Clicked = false;

        /// <summary>
        /// Depth level for sorting the control on screen
        /// </summary>
        public ControlDepth depth = ControlDepth.NonDrag;

        /// <summary>
        /// Gets/Sets the real screen x coordinates
        /// </summary>
        protected int _x;
        public virtual int x {
            get
            {
                return _x;
            }
            set
            {
                foreach (UserControl ctrl in controls)
                {
                    ctrl.x += value - _x;
                }
                _x = value;
            }
        }

        /// <summary>
        /// Gets/Sets the real screen x coordinates
        /// </summary>
        protected int _y;
        public virtual int y
        {
            get
            {
                return _y;
            }
            set
            {
                foreach (UserControl ctrl in controls)
                {
                    ctrl.y += (value - _y);
                }
                _y = value;
            }
        }

        /// <summary>
        /// Gets the control width
        /// </summary>
        protected  int _width;
        public virtual int width
        {
            get
            {
                return _width;
            }
            set
            {
                foreach (UserControl ctrl in controls)
                {
                    switch (ctrl.xAnchor)
                    {
                        case HorizontalAnchor.Left:
                            ctrl.x = ctrl.x;
                            break;
                        case HorizontalAnchor.Middle:
                            ctrl.x = Util.getCentreDrawPointX(x, value, ctrl.width);
                            break;
                        case HorizontalAnchor.Right:
                            ctrl.x += (value - _width);
                            break;
                        case HorizontalAnchor.None:

                            break;
                    }
                    if (ctrl.expandWidth)
                        ctrl.width += (value - _width);
                }
                _width = value;
            }
        }


        /// <summary>
        /// The control height
        /// </summary>
        protected int _height;
        public virtual int height
        {
            get
            {
                return _height;
            }
            set
            {
                foreach (UserControl ctrl in controls)
                {
                    switch (ctrl.yAnchor)
                    {
                        case VerticleAnchor.Top:
                            ctrl.x = ctrl.x;
                            break;
                        case VerticleAnchor.Middle:
                            ctrl.y = Util.getCentreDrawPointY(y, value, ctrl.height);
                            break;
                        case VerticleAnchor.Bottom:
                            ctrl.y += (value - _height);
                            break;
                        case VerticleAnchor.None:

                            break;
                    }
                   
                }
                _height = value;
            }
        }

        /// <summary>
        /// List of controls contained with in this control (controlception)
        /// </summary>
        public List<UserControl> controls;

        /// <summary>
        /// Gets the selected control within the control
        /// </summary>
        protected UserControl SelectedControl = null;
        protected UserControl HoverControl = null;

        /// <summary>
        /// Opacity of the control (0.0f - 1.0f
        /// </summary>
        public float opacity = 1.0f;

        #endregion

        #region Virtual Methods

        /// <summary>
        /// Unloads related content in User Control
        /// </summary>
        virtual public void LoadContent()
        {
            _bgTexture = TacticsGame.Instance.Content.Load<Texture2D>(Constants.TextureBlank);
        }

        /// <summary>
        /// Unloads related content in User Control
        /// </summary>
        virtual public void UnloadContent()
        {

        }

        /// <summary>
        /// Logic for dragging a control
        /// </summary>
        virtual public void HandleDrag()
        {
            int mX, mY;
            InputMgr.Instance.getMouse(out mX, out mY);

            if (Held)
            {
                if (lastX > -1 || lastY > -1)
                {
                    int changeX = (mX - lastX);
                    int changeY = (mY - lastY);
                    x += changeX;
                    y += changeY;

                    foreach (UserControl control in controls)
                    {
                        control.x += changeX;
                        control.y += changeY;
                    }
                }
                lastX = mX;
                lastY = mY;
            }
            else
            {
                lastX = -1;
                lastY = -1;
            }

        }


        /// <summary>
        /// Updates Control Logic, cycles through subcontrols and updates logic
        /// </summary>
        virtual public void Update(GameTime gameTime)
        {
             bool controlCollisionFound = false;
             HoverControl = null;

             UserControl ctrl;
                 for (int i = controls.Count - 1; i > -1; i--)
                 {
                     ctrl = controls[i];
                     int cX, cY;
                     InputMgr.Instance.getMouse(out cX, out cY);
                     ctrl.Hover = false;
                     ctrl.Clicked = false;

                     if (!controlCollisionFound)
                     {
                         if ((cX >= ctrl.x) && (cX < ctrl.x + ctrl.width)
                             && (cY >= ctrl.y) && (cY < ctrl.y + ctrl.height))
                         {
                             ctrl.Hover = true;
                             controlCollisionFound = true;
                             HoverControl = ctrl;

                             if (InputMgr.Instance.isMouseClickDown(Click.Left))
                             {
                                 if (SelectedControl != null)
                                 {
                                     SelectedControl.Selected = false;
                                 }
                                 SelectedControl = ctrl;
                                 ctrl.Selected = true;
                                 ctrl.Clicked = true;
                             }
                         }
                     }
                     ctrl.Update(gameTime);
                     updateStatus.AddRange(ctrl.updateStatus);
                     ctrl.updateStatus.Clear();
                 }

                 if (isDraggable)
                 {
                     HandleDrag();
                 }

                 if (Hover)
                     HandleHover();
                 if (Clicked)
                     HandleClick();

                 HandleState();

        }

        /// <summary>
        /// Draws control and sub controls
        /// </summary>
        virtual public void Draw(GameTime gameTime)
        {
            foreach (UserControl control in controls)
            {
                control.Draw(gameTime);
            }            
        }

        virtual public void SortControls()
        {
            foreach (UserControl ctrl in controls)
            {
                ctrl.SortControls();
            }
            controls.Sort(delegate(UserControl c1, UserControl c2) { return c1.depth.CompareTo(c2.depth); });
        }

        /// <summary>
        /// Actions for when controls states change
        /// </summary>
        virtual public void HandleState()
        {
                
        }

        /// <summary>
        /// Action for when control is hovered over
        /// </summary>
        virtual public void HandleHover()
        {

        }

        /// <summary>
        /// Handles click action on control
        /// </summary>
        virtual public void HandleClick()
        {

        }
        
        #endregion

        #region Constructor
        /// <summary>
        /// Constructs basic parameters and initalizes subcontrols
        /// </summary>
        public UserControl()
        {
            controls = new List<UserControl>();
            singleton = false;
            modar = false;
        }
        #endregion

   
    }
}
